<?php
// +----------------------------------------------------------------------
// | INPHP
// +----------------------------------------------------------------------
// | Copyright (c) 2021 https://inphp.cc All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/MIT )
// +----------------------------------------------------------------------
// | Author: lulanyin <me@lanyin.lu>
// +----------------------------------------------------------------------
//                        全局事件监听和通知
// +----------------------------------------------------------------------
namespace Inphp;

class Events
{
    /**
     * 事件列表
     * @var array
     */
    public static array $event_list = [];

    /**
     * 监听事件
     * @param string $name      事件名称
     * @param mixed $callback   回调方法
     * @param bool $once        是否属于一次性事件，即：事件通知后，立刻销毁，注意，如果该事件属于一次性事件，同名事件会被一并销毁
     */
    public static function listen(string $name, mixed $callback, bool $once = false)
    {
        if(!isset(self::$event_list[$name]))
        {
            $events = [
                "once"  => $once,
                "events"=> [$callback]
            ];
        }
        else
        {
            $events = self::$event_list[$name];
            $events["once"] = $once;
            $events["events"][] = $callback;
        }
        self::$event_list[$name] = $events;
    }

    /**
     * 执行事件通知
     * @param string $name
     * @param array $args
     * @return mixed
     */
    public static function emit(string $name, array $args = []): array
    {
        $res = [];
        if(isset(self::$event_list[$name]))
        {
            $events = self::$event_list[$name];
            if(!empty($events['events']))
            {
                foreach ($events['events'] as $event)
                {
                    if(is_array($event)){
                        //[__class__, 'static method']
                        $_class = $event[0];
                        $_method = $event[1] ?? null;
                        if(class_exists($_class) && !empty($_method)){
                            $res[] = call_user_func_array([$_class, $_method], $args);
                        }
                    }elseif($event instanceof \Closure){
                        $res[] = $event($args);
                    }elseif(function_exists($event)){
                        $res[] = call_user_func_array($event, $args);
                    }
                }
            }
            if($events['once'])
            {
                unset(self::$event_list[$name]);
            }
        }
        return $res;
    }
}